package com.isyscore.os.etl.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.ImmutableMap;
import com.isyscore.boot.mybatis.PageRequest;
import com.isyscore.device.common.model.RespDTO;
import com.isyscore.device.common.util.JsonMapper;
import com.isyscore.os.core.exception.DataFactoryException;
import com.isyscore.os.core.exception.ErrorCode;
import com.isyscore.os.core.model.entity.JobConfig;
import com.isyscore.os.core.model.entity.JobRunLog;
import com.isyscore.os.etl.model.Insert;
import com.isyscore.os.etl.model.Update;
import com.isyscore.os.etl.model.dto.JobComponent;
import com.isyscore.os.etl.model.form.JobParam;
import com.isyscore.os.etl.model.form.JobViewable;
import com.isyscore.os.etl.service.JobConfigService;
import com.isyscore.os.etl.service.JobRunLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Api(tags = "任务相关")
@RestController
@RequestMapping("${api-full-prefix}/jobs")
@Slf4j
@RequiredArgsConstructor
public class JobConfigController {

    private final JobConfigService jobConfigService;

    private final JobRunLogService jobRunLogService;


    @ApiOperation("可视化任务录入")
    @PostMapping("/viewable")
    public RespDTO<Map> addViewable(@RequestBody @Validated(Insert.class) JobViewable jobViewable) {
        return jobConfigService.saveViewable(jobViewable);
    }

    @ApiOperation("可视化任务查询")
    @GetMapping("/viewable/{id}")
    public RespDTO<JobViewable> getViewable(@PathVariable("id") String id) {
        JobConfig jobConfig = Optional.ofNullable(jobConfigService.getById(id)).orElseThrow(() -> new DataFactoryException(ErrorCode.JOB_DOES_NOT_EXISTS));
        JobViewable jobViewable = new JobViewable();
        BeanUtils.copyProperties(jobConfig, jobViewable);
        String configJson = jobConfig.getViewableConfig();
        if (!StringUtils.isEmpty(configJson)) {
            List<JobComponent> components = JsonMapper.fromJsonToList(configJson, JobComponent.class);
            jobViewable.setComponents(components);
        }
        return RespDTO.onSuc(jobViewable);
    }

    @ApiOperation("可视化任务更新")
    @PutMapping("/viewable")
    public RespDTO updateViewable(@RequestBody @Validated(Update.class) JobViewable jobViewable) {
        jobConfigService.updateViewable(jobViewable);
        return RespDTO.onSuc();
    }

    @ApiOperation("Flink SQL 预览")
    @PostMapping("/sqlPreview")
    public RespDTO<Map> preview (@RequestBody List<JobComponent> components) {
        String sql = jobConfigService.preview(components);
        return RespDTO.onSuc(ImmutableMap.of("sql", sql == null ? "" : sql));
    }

    @ApiOperation("任务录入")
    @PostMapping("/add")
    public RespDTO addJob(@RequestBody @Validated JobConfig jobConfig) {
        return jobConfigService.addJob(jobConfig);
    }

    @ApiOperation("更新任务配置")
    @PostMapping("/update")
    public RespDTO updateJob(@RequestBody @Validated JobConfig jobConfig) {
        return jobConfigService.updateJobConfig(jobConfig);
    }

    @ApiOperation("任务可编辑")
    @GetMapping("/open")
    public RespDTO open(@RequestParam("id") String id) {
        return jobConfigService.openJob(id);
    }

    @ApiOperation("任务不可编辑")
    @GetMapping("/close")
    public RespDTO close(@RequestParam("id") String id) {
        return jobConfigService.closeJob(id);
    }



    @ApiOperation("删除任务配置")
    @DeleteMapping("/delete")
    public RespDTO deleteJob(@RequestParam("id") String id) {
        jobConfigService.deleteJobConfigById(id);
        return RespDTO.onSuc();
    }

    @ApiOperation("启动任务")
    @PutMapping("/start")
    public RespDTO startJob(@RequestBody JobParam jobParam) {
        return jobConfigService.startJob(jobParam.getId());
    }

    @ApiOperation("停止任务")
    @PutMapping("/stop")
    public RespDTO stopJob(@RequestBody JobParam jobParam) {
        return jobConfigService.stopJob(jobParam.getId());
    }


    @ApiOperation("查询任务详情")
    @GetMapping("{id}")
    public RespDTO<JobConfig> get(@PathVariable("id") String id) {
        return RespDTO.onSuc(jobConfigService.getById(id));
    }

    @ApiOperation("分页查询任务列表")
    @GetMapping
    public RespDTO<IPage<JobConfig>> page(JobConfig jobConfig, PageRequest page) {
        ArrayList<String> order = new ArrayList<>();
        order.add("created_at.desc");
        page.setOrders(order);
        return RespDTO.onSuc(jobConfigService.page(page.toPage(), new QueryWrapper<>(jobConfig)));
    }

    @ApiOperation("分页查询任务日志列表")
    @GetMapping("/logList")
    public RespDTO<IPage<JobRunLog>> logList(JobRunLog jobRunLog, PageRequest page) {
        ArrayList<String> order = new ArrayList<>();
        order.add("created_at.desc");
        page.setOrders(order);
        return RespDTO.onSuc(jobRunLogService.page(page.toPage(), new QueryWrapper<>(jobRunLog)));
    }


    @ApiOperation("开启/关闭调度")
    @PutMapping("/schedule/{id}/{isScheduled}")
    public RespDTO<Void> schedule (@PathVariable("id") String id, @PathVariable("isScheduled") Integer isStart) {
        jobConfigService.schedule(id, isStart);
        return RespDTO.onSuc();
    }

    @ApiOperation("手动关闭调度")
    @GetMapping("/manually/{id}")
    public RespDTO<Void> manuallyStop(@PathVariable("id") String id) {
        jobConfigService.manuallyStop(id);
        return RespDTO.onSuc();
    }
}
